package com.link2room.rodimus.facade.impl;

import com.link2room.common.constant.BaseConstant;
import com.link2room.common.constant.DefaultValue;
import com.link2room.common.dto.param.base.BaseL2rParamDto;
import com.link2room.common.dto.result.base.MemberSessionDto;
import com.link2room.common.dto.threadlocal.ApiThreadLocal;
import com.link2room.common.dto.threadlocal.BaseThreadLocal;
import com.link2room.common.exception.SysException;
import com.link2room.common.jpa.condition.ConditionDetail;
import com.link2room.common.jpa.condition.L2RCondition;
import com.link2room.common.jpa.criteria.CriteriaUtil;
import com.link2room.common.jpa.result.QueryResult;
import com.link2room.common.mns.MNSUtil;
import com.link2room.common.service.ICommonService;
import com.link2room.common.util.*;
import com.link2room.enums.exception.RodimusSysExceptionEnum;
import com.link2room.rodimus.constant.*;
import com.link2room.rodimus.dto.param.api.*;
import com.link2room.rodimus.dto.param.base.InvoiceBaseParamDto;
import com.link2room.rodimus.dto.param.inside.ExpressNewInsideParamDto;
import com.link2room.rodimus.dto.result.base.*;
import com.link2room.rodimus.entity.*;
import com.link2room.rodimus.facade.IMallApiFacadeService;
import com.link2room.rodimus.feign.rodimus.ExpressFeignService;
import com.link2room.rodimus.feign.soundwave.PmsMemberFeignService;
import com.link2room.rodimus.feign.trailbreaker.PrepayFeignService;
import com.link2room.rodimus.listener.event.MallOrderPaySuccessEvent;
import com.link2room.rodimus.service.IGroupBuyingService;
import com.link2room.rodimus.service.IMallOrderService;
import com.link2room.rodimus.util.InvoiceUtil;
import com.link2room.soundwave.constant.L2RPointConstant;
import com.link2room.soundwave.dto.param.inside.MemberLoginInsideParamDto;
import com.link2room.soundwave.dto.param.inside.PointPresentUseInsideParamDto;
import com.link2room.soundwave.dto.result.base.PmsCardBalanceDto;
import com.link2room.trailbreaker.constant.Pay;
import com.link2room.trailbreaker.dto.param.PrePayParamDto;
import com.link2room.trailbreaker.dto.result.PrepayResDto;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.link2room.enums.exception.RodimusSysExceptionEnum.MALL_ORDER_CANCEL_ERROR;


/**
 * Created by VegetaKo on 2017/1/4.
 */
@Service("mallApiFacadeService")
public class MallApiFacadeServiceImpl implements IMallApiFacadeService {
    @Resource
    private ICommonService commonService;

    @Autowired
    private PmsMemberFeignService pmsMemberFeignService;

    @Autowired
    private ExpressFeignService expressFeignService;
    @Autowired
    private PrepayFeignService prepayFeignService;
    @Resource
    private IMallOrderService mallOrderService;
    @Resource
    private MNSUtil mnsUtil;
    @Resource
    private IGroupBuyingService groupBuyingService;
    @Autowired
    private ApplicationEventPublisher publisher;

    @Override
    public QueryResult<MallGoodCategory> getGoodCategorysList() throws Exception {
        BaseL2rParamDto paramDto = new BaseL2rParamDto();
        MallGoodCategory mallGoodCategory = new MallGoodCategory();
        mallGoodCategory.setLhotelGroupCode(paramDto.getLhotelGroupCode());
        QueryResult<MallGoodCategory> mallGoodCategoryQueryResult = commonService.findAllEQ(MallGoodCategory.class, mallGoodCategory, paramDto.getCurrentPage(), paramDto.getPageSize());
        return mallGoodCategoryQueryResult;
    }

    @Override
    public QueryResult<MallGoodBaseApiDto> getGoodsList(MallGoodsApiParamDto mallGoodsApiParamDto) throws Exception {
        String lhotelGroupCode = mallGoodsApiParamDto.getLhotelGroupCode();
        L2RAssert.stringBlank(lhotelGroupCode, "[lhotelGroupCode] is null.");
        Integer pageSize = mallGoodsApiParamDto.getPageSize();
        if (pageSize == null) {
            pageSize = 10;
        }
        Integer currentPage = mallGoodsApiParamDto.getCurrentPage();
        if (currentPage == null) {
            currentPage = 1;
        }
        MallGoodBase mallGoodBase = new MallGoodBase();
        mallGoodBase.setLhotelGroupCode(lhotelGroupCode);
        mallGoodBase.setGoodCategory(mallGoodsApiParamDto.getGoodCategory());
        mallGoodBase.setIsHalt(BaseConstant.BaseDaoPropertyConstant.IsHalt.notHalt);
        mallGoodBase.setIsHot(mallGoodsApiParamDto.getIsHot());
        HashMap<String, String> orderMap = new HashMap<String, String>();
        QueryResult<MallGoodBase> mallGoodBaseQueryResult;
        String orderBy = mallGoodsApiParamDto.getOrderBy();
        String isAsc = mallGoodsApiParamDto.getIsAsc();
        if (StringUtil.isNotBlank(orderBy) &&
                Arrays.stream(MallGoodBase.MallGoodBase_.values()) //是否存在排序字段
                        .anyMatch(item -> item.toString().equals(orderBy))
                ) {
            if (DefaultValue.T.equals(isAsc)) {
                orderMap.put(orderBy, CriteriaUtil.ASC);
            } else {
                orderMap.put(orderBy, CriteriaUtil.DESC);
            }
        } else {
            if (StringUtil.isNotBlank(mallGoodsApiParamDto.getSort())) { //兼容原来的积分排序参数
                if (mallGoodsApiParamDto.getSort().equals(MallGoodsConstant.Sort.pointAsc)) {
                    orderMap.put(MallGoodBase.MallGoodBase_.defaultPoint.toString(), CriteriaUtil.ASC);
                } else if (mallGoodsApiParamDto.getSort().equals(MallGoodsConstant.Sort.pointDesc)) {
                    orderMap.put(MallGoodBase.MallGoodBase_.defaultPoint.toString(), CriteriaUtil.DESC);
                }
            }
        }
        mallGoodBaseQueryResult = commonService.findAllEQ(MallGoodBase.class, mallGoodBase, currentPage, pageSize, orderMap, null);
        QueryResult<MallGoodBaseApiDto> res = ClassConverUtil.copyQueryResultToDtoQueryResult(mallGoodBaseQueryResult, MallGoodBaseApiDto.class, true);
        if (res != null && CollectionUtils.isNotEmpty(res.getResultlist())) {
            res.getResultlist().stream().forEach(mallGoodBaseDto -> {
                String goodType = mallGoodBaseDto.getGoodType();
                String extra = mallGoodBaseDto.getGoodExtra();
                if(StringUtil.isBlank(extra)){
                    return;
                }
                if (MallGoodsConstant.GoodType.PMSCOUPON.equals(goodType)) {
                    MallGoodBaseExtraPMSCouponDto couponDto = JacksonUtil.jsonToBean(extra, MallGoodBaseExtraPMSCouponDto.class);
                    mallGoodBaseDto.setMallGoodBaseExtraPMSCoupon(couponDto);
                } else if (MallGoodsConstant.GoodType.PMSPACKAGE.equals(goodType)) {
                    mallGoodBaseDto.setMallGoodBaseExtraPMSPackage(JacksonUtil.jsonToBean(extra, MallGoodBaseExtraPMSPackageDto.class));
                }
            });
        }
        return res;

       /* if (StringUtil.isNotBlank(mallGoodsApiParamDto.getSort())) {
            if (mallGoodsApiParamDto.getSort().equals(MallGoodsConstant.Sort.pointAsc)) {
                orderMap.put(MallGoodBase.MallGoodBase_.defaultPoint.toString(), CriteriaUtil.ASC);
            } else if (mallGoodsApiParamDto.getSort().equals(MallGoodsConstant.Sort.pointDesc)) {
                orderMap.put(MallGoodBase.MallGoodBase_.defaultPoint.toString(), CriteriaUtil.DESC);
            }

        } else {
            mallGoodBaseQueryResult = commonService.findAllEQ(MallGoodBase.class, mallGoodBase, mallGoodsApiParamDto.getCurrentPage(), mallGoodsApiParamDto.getPageSize());
        }
*/
    }


    @Override
    public MallGoodBaseApiDto getGoodById(MallGoodsApiParamDto mallGoodsApiParamDto) throws Exception {
        MallGoodBase mallGoodBase = commonService.findOneById(MallGoodBase.class, mallGoodsApiParamDto.getId());
        MallGoodBaseApiDto mallGoodBaseDto = ClassConverUtil.copyPropertiesToDto(mallGoodBase, MallGoodBaseApiDto.class, true);
        MallGoodPrice mallGoodPriceFinder = new MallGoodPrice();
        mallGoodPriceFinder.setLhotelGroupCode(mallGoodsApiParamDto.getLhotelGroupCode());
        mallGoodPriceFinder.setGoodCode(mallGoodBaseDto.getGoodCode());
        QueryResult<MallGoodPrice> mallGoodPriceDtoQuery = commonService.findAllEQ(MallGoodPrice.class, mallGoodPriceFinder);
        QueryResult<MallGoodPriceDto> mallGoodPriceDtoQueryResult = ClassConverUtil.copyQueryResultToDtoQueryResult(mallGoodPriceDtoQuery, MallGoodPriceDto.class, true);
        mallGoodBaseDto.setPriceDtoList(mallGoodPriceDtoQueryResult.getResultlist());
        return mallGoodBaseDto;
    }

    @Override
    public MallGoodBaseApiDto getGoodByCode(MallGoodsApiParamDto mallGoodsApiParamDto) throws Exception {
        String goodCode = mallGoodsApiParamDto.getGoodCode();
        L2RAssert.stringBlank(goodCode, "[goodCode] is null.");
        MallGoodBase find = new MallGoodBase();
        find.setGoodCode(goodCode);
        find.setLhotelGroupCode(mallGoodsApiParamDto.getLhotelGroupCode());
        MallGoodBase qres = commonService.findOneEQ(MallGoodBase.class, find);

        if (qres == null) {
            return null;
        }

        MallGoodBaseApiDto mallGoodBaseDto = ClassConverUtil.copyPropertiesToDto(qres, MallGoodBaseApiDto.class, true);
        MallGoodPrice mallGoodPriceFinder = new MallGoodPrice();
        mallGoodPriceFinder.setLhotelGroupCode(mallGoodsApiParamDto.getLhotelGroupCode());
        mallGoodPriceFinder.setGoodCode(mallGoodBaseDto.getGoodCode());
        QueryResult<MallGoodPrice> mallGoodPriceDtoQuery = commonService.findAllEQ(MallGoodPrice.class, mallGoodPriceFinder);
        QueryResult<MallGoodPriceDto> mallGoodPriceDtoQueryResult = ClassConverUtil.copyQueryResultToDtoQueryResult(mallGoodPriceDtoQuery, MallGoodPriceDto.class, true);
        mallGoodBaseDto.setPriceDtoList(mallGoodPriceDtoQueryResult.getResultlist());

        String goodType = mallGoodBaseDto.getGoodType();
        String extra = mallGoodBaseDto.getGoodExtra();

        if (StringUtil.isNotBlank(extra) && MallGoodsConstant.GoodType.PMSCOUPON.equals(goodType)) {
            MallGoodBaseExtraPMSCouponDto couponDto = JacksonUtil.jsonToBean(extra, MallGoodBaseExtraPMSCouponDto.class);
            mallGoodBaseDto.setMallGoodBaseExtraPMSCoupon(couponDto);
        }else if (StringUtil.isNotBlank(extra) && MallGoodsConstant.GoodType.PMSPACKAGE.equals(goodType)) {
            mallGoodBaseDto.setMallGoodBaseExtraPMSPackage(JacksonUtil.jsonToBean(extra, MallGoodBaseExtraPMSPackageDto.class));
        }

        return mallGoodBaseDto;
    }

    @Override
    public QueryResult<MallOrderBaseDto> getOrders(MallOrderApiParamDto mallOrderApiParamDto) throws Exception {
        String orderType = mallOrderApiParamDto.getOrderType();
        String productCode = mallOrderApiParamDto.getProductCode();
        MemberSessionDto memberSessionDto = ApiThreadLocal.getMemberSessionThreadLocal();
        L2RCondition condition = new L2RCondition();
        condition.setOrConditions(
                new ConditionDetail[]{
                        new ConditionDetail(MallOrderBase.MallOrderBase_.memberNo.toString(), CriteriaUtil.Operator.EQ, memberSessionDto.getMemberNo()),
                        new ConditionDetail(MallOrderBase.MallOrderBase_.openid.toString(), CriteriaUtil.Operator.EQ, memberSessionDto.getOpenid())
                }
        );
        condition.setAndConditions(
                new ConditionDetail[]{
                        new ConditionDetail(MallOrderBase.BaseEntity_.lhotelGroupCode.toString(), CriteriaUtil.Operator.EQ, mallOrderApiParamDto.getLhotelGroupCode()),
                        new ConditionDetail(MallOrderBase.MallOrderBase_.orderType.toString(), CriteriaUtil.Operator.EQ, orderType),
                        new ConditionDetail(MallOrderBase.MallOrderBase_.productCode.toString(), CriteriaUtil.Operator.EQ, productCode),
                }
        );

        HashMap<String, String> orderBy = new HashMap<>();
        orderBy.put(CouponPresentBaseEntity.BaseEntity_.id.toString(), CriteriaUtil.DESC.toString());

        QueryResult<MallOrderBase> mallOrderBaseQueryResult = commonService.findAllByCondition(
                MallOrderBase.class,
                condition,
                mallOrderApiParamDto.getCurrentPage(),
                mallOrderApiParamDto.getPageSize(),
                orderBy,
                null
        );
        if (mallOrderBaseQueryResult == null || CollectionUtils.isEmpty(mallOrderBaseQueryResult.getResultlist())) {
            QueryResult emptyRes = new QueryResult<>();
            emptyRes.setCurrentPage(1);
            emptyRes.setTotalrecord(0);
            emptyRes.setResultlist(Collections.EMPTY_LIST);
            return emptyRes;
        }

        List<String> orderCodes = mallOrderBaseQueryResult.getResultlist()
                .stream()
                .map(MallOrderBase::getOrderCode)
                .distinct()
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.toList());

        Map<String, List<MallOrderPriceDto>> mallOrderPrices = selectMallOrderPirceByCode(mallOrderApiParamDto.getLhotelGroupCode(), orderCodes);
        QueryResult<MallOrderBaseDto> res = ClassConverUtil.copyQueryResultToDtoQueryResult(mallOrderBaseQueryResult, MallOrderBaseDto.class, false);
        res.getResultlist()
                .forEach(orderBaseDto -> orderBaseDto.setMallOrderPriceDtos(mallOrderPrices.get(orderBaseDto.getOrderCode())));
        return res;
    }


    private Map<String, List<MallOrderPriceDto>> selectMallOrderPirceByCode(String lhotelGroupCode, List<String> orderNos) throws Exception {

        if (CollectionUtils.isEmpty(orderNos)) {
            return Collections.EMPTY_MAP;
        }
        L2RCondition condition = new L2RCondition();

        condition.setAndConditions(
                new ConditionDetail[]{
                        new ConditionDetail(MallOrderPrice.MallOrderPrice_.orderCode.toString(), CriteriaUtil.Operator.IN, orderNos),
                        new ConditionDetail(MallOrderPrice.BaseEntity_.lhotelGroupCode.toString(), CriteriaUtil.Operator.EQ, lhotelGroupCode),
                }
        );

        QueryResult<MallOrderPrice> qres = commonService.findAllByCondition(MallOrderPrice.class, condition);
        if (qres == null || CollectionUtils.isEmpty(qres.getResultlist())) {
            return Collections.EMPTY_MAP;
        } else {
            Map<String, List<MallOrderPriceDto>> res = new HashMap<>();
            qres.getResultlist()
                    .stream()
                    .collect(Collectors.groupingBy(MallOrderPrice::getOrderCode))
                    .forEach((key, value) -> {
                        List<MallOrderPriceDto> s = value.stream()
                                .map(entity -> ClassConverUtil.copyProperties(entity, MallOrderPriceDto.class))
                                .collect(Collectors.toList());
                        res.put(key, s);
                    });

            return res;
        }
    }

    @Override
    public MallOrderBaseDto getOrder(MallOrderApiParamDto mallOrderApiParamDto) throws Exception {

        MemberSessionDto memberSessionDto = ApiThreadLocal.getMemberSessionThreadLocal();
        if (null == memberSessionDto) {
            throw new SysException(RodimusSysExceptionEnum.LONGIN_ERRO.getCode(), RodimusSysExceptionEnum.LONGIN_ERRO.getMsg() + "", RodimusSysExceptionEnum.LONGIN_ERRO.getBizType());
        }
        if (StringUtil.isBlank(memberSessionDto.getMemberNo()) && StringUtil.isBlank(memberSessionDto.getOpenid())) {
            throw new SysException(RodimusSysExceptionEnum.LONGIN_ERRO.getCode(), RodimusSysExceptionEnum.LONGIN_ERRO.getMsg() + "", RodimusSysExceptionEnum.LONGIN_ERRO.getBizType());
        }
        Long id = mallOrderApiParamDto.getId();
        L2RAssert.numberNull(id, "[id] is null");
        MallOrderBase mallOrderBase = new MallOrderBase();
       /* if(StringUtil.isBlank(memberSessionDto.getMemberNo())){
            mallOrderBase.setMemberNo(memberSessionDto.getMemberNo() );
        }else {
            mallOrderBase.setOpenid(memberSessionDto.getOpenid());
        }*/
        mallOrderBase.setId(mallOrderApiParamDto.getId());
        mallOrderBase.setLhotelGroupCode(mallOrderApiParamDto.getLhotelGroupCode());
        mallOrderBase = commonService.findOneEQ(MallOrderBase.class, mallOrderBase);
        MallOrderBaseDto mallOrderBaseDto = ClassConverUtil.copyPropertiesToDto(mallOrderBase, MallOrderBaseDto.class, false);
        MallOrderPrice mallOrderPrice = new MallOrderPrice();

        mallOrderPrice.setLhotelGroupCode(mallOrderApiParamDto.getLhotelGroupCode());
        mallOrderPrice.setOrderCode(mallOrderBase.getOrderCode());
        QueryResult<MallOrderPrice> mallOrderPriceQueryResult = commonService.findAllEQ(MallOrderPrice.class, mallOrderPrice);
        QueryResult<MallOrderPriceDto> mallOrderPriceDtoQueryResult = ClassConverUtil.copyQueryResultToDtoQueryResult(mallOrderPriceQueryResult, MallOrderPriceDto.class, true);
        for (MallOrderPriceDto mopd : mallOrderPriceDtoQueryResult.getResultlist()) {
            if (StringUtil.isBlank(mopd.getName())) {
                continue; // 因为MallOrderPriceEntity增加name等商品详情字段冗余，这里为兼容旧数据，没有再查询.
            }
            MallGoodBase mallGoodBase = new MallGoodBase();
            mallGoodBase.setGoodCode(mopd.getGoodCode());
            mallGoodBase = commonService.findOneEQ(MallGoodBase.class, mallGoodBase);
            if (mallGoodBase == null) {
                continue;
            }
            mopd.setName(mallGoodBase.getName());
            mopd.setLogo(mallGoodBase.getLogo());
            mopd.setPictures(mallGoodBase.getPictures());
            mallOrderBaseDto.setLogo(mallGoodBase.getLogo());
        }

        mallOrderBaseDto.setMallOrderPriceDtos(mallOrderPriceDtoQueryResult.getResultlist());

        //添加prepay方法.预下单调用prepay接口
//        if (MallOrderConstant.Sta.needPay.equals(mallOrderBaseDto.getSta())) {
//            // List params=new ArrayList<>();
//            // params.add("MALLPRICE");
//            //String newMallOrderPayNo= commonService.findOneFieldByProcedure("create_No",params);
//
//
//            PrePayParamDto payParamDto = new PrePayParamDto();
//
//            payParamDto.setPayChannel(mallOrderApiParamDto.getPayChannel());
//            payParamDto.setPayType(mallOrderApiParamDto.getPayType());
//            payParamDto.setLhotelGroupCode(mallOrderApiParamDto.getLhotelGroupCode());
//            payParamDto.setLhotelCode(mallOrderApiParamDto.getLhotelCode());
//            payParamDto.setSpBillCreateIP(BaseThreadLocal.getRemoteAddr());
//            payParamDto.setGoodName("商城物品");
//            payParamDto.setOpenid(memberSessionDto.getOpenid());
//            if (CollectionUtils.isNotEmpty(mallOrderBaseDto.getMallOrderPriceDtos())) {
//                payParamDto.setGoodsTag(mallOrderBaseDto.getMallOrderPriceDtos().get(0).getPriceCode());
//            }
//            payParamDto.setOrderNo(mallOrderBase.getOrderCode());
//            payParamDto.setTotalFee(mallOrderBaseDto.getPrice());
//            payParamDto.setNotifyService(RodimusServiceCodeConstant.SERVICE_MALLORDERPAYNOTIFY);
//            PrepayResDto payRes = trailbreakerAPIService.prePay(payParamDto);
//            String l2rPrepayId = payRes.getL2rPrepayId();
//            mallOrderBaseDto.setL2rPrepayId(l2rPrepayId);
//        }

        return mallOrderBaseDto;
    }

    @Override
    public MallOrderBaseDto newOrder(MallOrderApiParamDto mallOrderApiParamDto) throws Exception {
        MemberSessionDto memberSessionDto = ApiThreadLocal.getMemberSessionThreadLocal();
        int autoCancelSecond = 24 * 60 * 60;//取消时间
        Date cancelDate = DateUtil.addSeconds(new Date(), autoCancelSecond);
        MallOrderBase mallOrderBase = new MallOrderBase();
        mallOrderBase.setCancelDate(cancelDate);
        ClassConverUtil.copyProperties(mallOrderApiParamDto.getMallOrderBaseApiParamDto(), mallOrderBase);


        InvoiceDetailDto invoiceDetailDto = mallOrderApiParamDto.getInvoiceDetailDto();
        String needInvoice = mallOrderBase.getNeedInvoice();
        if (StringUtil.isNotBlank(needInvoice) && DefaultValue.T.equals(needInvoice)) {
            checkInvoice(invoiceDetailDto);
            mallOrderBase.setInvoiceTitle(invoiceDetailDto.getInvoiceTitle());
            mallOrderBase.setInvoiceRemark(
                    StringUtils.join(Arrays.asList(
                            invoiceDetailDto.getInvoiceTitleTypeDes(),
                            invoiceDetailDto.getInvoiceTypeDes(),
                            invoiceDetailDto.getPayerDes(),
                            invoiceDetailDto.getProviderDes(),
                            invoiceDetailDto.getEarlyPrepareDes(),
                            invoiceDetailDto.getPostTypeDes()

                            ).stream().filter(StringUtil::isNotBlank).toArray()
                            , ",")
            );
        }
        mallOrderBase.setNeedInvoice(needInvoice);

//        //0 初始化
        List<MallOrderPrice> mallOrderPrices = new ArrayList<>();
//        List params = new ArrayList<>();
//        params.add("MALLORDER");
//        String newMallOrderNo = commonService.findOneFieldByProcedure("create_No", params);
        String newMallOrderNo = mallOrderService.generateNewOrderNo();
        //1.计算总的积分和总金额
        BigDecimal point = BigDecimal.ZERO;
        BigDecimal money = BigDecimal.ZERO;
        Set<String> goodNames = new HashSet<>();
        Set<String> goodCodes = new HashSet<>();
        String goodType = null; //由于现在是一单一个商品，所以只要取第一个商品的goodType就好。 之后需要做分商品扣减积分操作，类似购物车
        for (MallGoodBaseApiParamDto mgbapd : mallOrderApiParamDto.getMallGoodBaseApiParamDtoList()) {

            MallGoodBase mallGoodBaseFinder = new MallGoodBase();
            mallGoodBaseFinder.setLhotelGroupCode(mallOrderApiParamDto.getLhotelGroupCode());
            mallGoodBaseFinder.setGoodCode(mgbapd.getGoodCode());
            MallGoodBase mallGoodBase = commonService.findOneEQ(MallGoodBase.class, mallGoodBaseFinder);
            goodNames.add(mallGoodBase.getName());
            goodCodes.add(mallGoodBase.getGoodCode());
//            if( mallGoodBase.getGoodType().equals(MallGoodsConstant.GoodType.MG)){
//                mallOrderBase.setGoodType("MG");
//            }
            goodType = mallGoodBase.getGoodType();
            mallOrderBase.setGoodType(mallGoodBase.getGoodType());
            MallGoodPrice mallGoodPrice = new MallGoodPrice();
            mallGoodPrice.setLhotelGroupCode(mallOrderApiParamDto.getLhotelGroupCode());
            mallGoodPrice.setPriceCode(mgbapd.getPriceCode());
            mallGoodPrice = commonService.findOneEQ(MallGoodPrice.class, mallGoodPrice);
            point = point.add(mallGoodPrice.getPoint().multiply(new BigDecimal(mgbapd.getCount())));
            money = money.add(mallGoodPrice.getMoney().multiply(new BigDecimal(mgbapd.getCount())));

            MallOrderPrice mallOrderPrice = new MallOrderPrice();
            ClassConverUtil.copyProperties(mgbapd, mallOrderPrice);
            mallOrderPrice.setGoodCode(mgbapd.getGoodCode());
            mallOrderPrice.setOrderCode(newMallOrderNo);
            mallOrderPrice.setPoint(mallGoodPrice.getPoint());
            mallOrderPrice.setMoney(mallGoodPrice.getMoney());
            mallOrderPrice.setTotalPoint(mallGoodPrice.getPoint().multiply(new BigDecimal(mgbapd.getCount())));
            mallOrderPrice.setTotalMoney(mallGoodPrice.getMoney().multiply(new BigDecimal(mgbapd.getCount())));
            mallOrderPrice.setDescript(mallGoodBase.getDescript());
            mallOrderPrice.setDescriptM(mallGoodBase.getDescriptM());
            mallOrderPrice.setName(mallGoodBase.getName());
            mallOrderPrice.setLogo(mallGoodBase.getLogo());
            mallOrderPrice.setPictures(mallGoodBase.getPictures());
            mallOrderPrices.add(mallOrderPrice);

        }
        mallOrderBase.setGoodContant(
                (String) StringUtils.join(
                        goodNames.stream().filter(StringUtil::isNotBlank).toArray(),
                        ","
                ));

        //2.1根据积分值大于零进行处理
        if (point.compareTo(BigDecimal.ZERO) > 0) {
            //非会员 没有积分，异常处理
            L2RAssert.isTrue(DefaultValue.F.equals(memberSessionDto.getIsMember()), new SysException(RodimusSysExceptionEnum.MEMBERPOINT_NOT_ENOUGH, "非会员不能积分兑换"));
            //RodimusLoginBaseParamDto rodimusLoginBaseParamDto = new RodimusLoginBaseParamDto();
            MemberLoginInsideParamDto memberLoginInsideParamDto = new MemberLoginInsideParamDto();
            memberLoginInsideParamDto.setL2RMemberNo(memberSessionDto.getMemberNo());
            PmsCardBalanceDto pmsCardBalanceDto = pmsMemberFeignService.getCardBalanceInfo(memberLoginInsideParamDto.paramToMap()).getResultInfo();
            //判断是否有足够积分
            if (pmsCardBalanceDto == null || pmsCardBalanceDto.getPointBalance() == null || point.compareTo(pmsCardBalanceDto.getPointBalance()) > 0) {
                throw new SysException(RodimusSysExceptionEnum.MEMBERPOINT_NOT_ENOUGH.getCode(), RodimusSysExceptionEnum.MEMBERPOINT_NOT_ENOUGH.getMsg() + "", RodimusSysExceptionEnum.MEMBERPOINT_NOT_ENOUGH.getBizType());
            }
            //扣减积分
            PointPresentUseInsideParamDto pointPresentUseInsideParamDto = new PointPresentUseInsideParamDto();
            pointPresentUseInsideParamDto.setLhotelGroupCode(mallOrderApiParamDto.getLhotelGroupCode());
            pointPresentUseInsideParamDto.setL2rMemberNo(memberSessionDto.getMemberNo());
            pointPresentUseInsideParamDto.setPoint(point);
            pointPresentUseInsideParamDto.setRemark("L2R使用积分");
            pointPresentUseInsideParamDto.setPromotionTag("");
            pointPresentUseInsideParamDto.setSrcType(L2RPointConstant.SRC_TYPE.MALL);
            if(MallGoodsConstant.GoodType.PMSPACKAGE.equals(goodType)){
                pointPresentUseInsideParamDto.setGoodType(L2RPointConstant.GOOD_TYPE.PMSPACKAGE);
            }
            pmsMemberFeignService.usePoint(pointPresentUseInsideParamDto);

            mallOrderBase.setSta(MallOrderConstant.Sta.init);
            mallOrderBase.setPointPaySta(MallOrderConstant.PointPaySat.PAID);
        }
        //2.2根据金额大于零进行处理
        if (money.compareTo(BigDecimal.ZERO) > 0) {
            mallOrderBase.setSta(MallOrderConstant.Sta.needPay);
        }
        try {
            mallOrderBase.setLhotelGroupCode(mallOrderApiParamDto.getLhotelGroupCode());
            mallOrderBase.setOrderCode(newMallOrderNo);
            mallOrderBase.setMemberNo(memberSessionDto.getMemberNo());
            mallOrderBase.setOpenid(memberSessionDto.getOpenid());
            //添加销售员no
            String mobile = mallOrderApiParamDto.getSalesmanMobile();
            if (StringUtil.isNotBlank(mobile)) {
                SalesmanBase salesman = findSalemanByMobile(mallOrderApiParamDto.getLhotelGroupCode(), mobile);
                if (salesman != null) {
                    mallOrderBase.setSalesmanNo(salesman.getSalesmanNo());
                }
            }
            mallOrderBase.setPoint(point);
            mallOrderBase.setPrice(money);
            mallOrderBase.setAmount(mallOrderApiParamDto.getMallGoodBaseApiParamDtoList().size());

            if (MallGoodsConstant.GoodType.MG.equals(mallOrderBase.getGoodType())) {
                mallOrderBase.setNeedExpress("T");
                mallOrderBase.setExpressSta("INIT");
                mallOrderBase.setExpressRemark(mallOrderApiParamDto.getMallOrderBaseApiParamDto().getExpressRemark());
                mallOrderBase.setExpressAddress(mallOrderApiParamDto.getMallOrderBaseApiParamDto().getExpressAddress());
                mallOrderBase.setExpressMobile(mallOrderApiParamDto.getMallOrderBaseApiParamDto().getExpressMobile());
                mallOrderBase.setExpressMan(mallOrderApiParamDto.getMallOrderBaseApiParamDto().getExpressMan());
                if(MallOrderConstant.Sta.init.equals(mallOrderBase.getSta())){ //在支付成功后再创建发货信息
                    //新建发货信息
                    ExpressNewInsideParamDto expressParamDto = new ExpressNewInsideParamDto();
                    expressParamDto.setMemberNo(mallOrderBase.getMemberNo());
                    expressParamDto.setMobile(mallOrderApiParamDto.getMallOrderBaseApiParamDto().getExpressMobile());
                    expressParamDto.setAddress(mallOrderApiParamDto.getMallOrderBaseApiParamDto().getExpressAddress());
                    expressParamDto.setGoodAmount(mallOrderApiParamDto.getMallOrderBaseApiParamDto().getAmount());
                    expressParamDto.setGoodName(mallOrderBase.getGoodContant());
                    expressParamDto.setGoodCode(StringUtils.join(
                            goodCodes.stream().filter(StringUtil::isNotBlank).toArray(),
                            ","
                    ));
                    expressParamDto.setSourceNo(mallOrderBase.getOrderCode());
                    expressParamDto.setReceiverName(mallOrderApiParamDto.getMallOrderBaseApiParamDto().getExpressMan());
                    expressParamDto.setSourceType("MALL");
                    expressParamDto.setRemark("商城订单");
                    expressParamDto.setLhotelGroupCode(mallOrderApiParamDto.getLhotelGroupCode());
                    expressParamDto.setOpenid(mallOrderBase.getOpenid());
                    expressFeignService.newExpress(expressParamDto);
                }

            } else {
                mallOrderBase.setNeedExpress("F");
                mallOrderBase.setExpressSta("NONE");
                mallOrderBase.setExpressRemark(mallOrderApiParamDto.getMallOrderBaseApiParamDto().getExpressRemark());
            }

            mallOrderBase.setInvoiceNo(mallOrderApiParamDto.getMallOrderBaseApiParamDto().getInvoiceNo());
            mallOrderBase.setInvoiceTitle(mallOrderApiParamDto.getMallOrderBaseApiParamDto().getInvoiceTitle());
            mallOrderBase.setInvoiceRemark(mallOrderApiParamDto.getMallOrderBaseApiParamDto().getInvoiceRemark());
//        commonService.save(mallOrderBase);
            //mallOrderBase = commonService.findOneEQ()
       /* List<MallOrderPrice> mallOrderPrices =ClassConverUtil.copyPropertiesList( mallOrderApiParamDto.getMallGoodBaseApiParamDtoList(), MallOrderPrice.class);
        for (MallOrderPrice mop :mallOrderPrices ) {
            mop.setOrderCode(newMallOrderNo );
        }*/
//        commonService.saveList(mallOrderPrices);
            //在同一个事务中处理
            mallOrderService.saveNewMallOrder(mallOrderBase, mallOrderPrices);
        } catch (Exception e) {
            //下单异常后回滚积分
            addPMSPoint(memberSessionDto.getMemberNo(), point, "商城下单异常回滚",mallOrderBase.getGoodType());
            throw e;
        }

        //发票处理
        if (StringUtil.isNotBlank(needInvoice) && DefaultValue.T.equals(needInvoice)) {
            invoiceDetailDto.setLhotelGroupCode(mallOrderBase.getLhotelGroupCode());
            invoiceDetailDto.setLhotelCode(mallOrderBase.getLhotelCode());
            invoiceDetailDto.setOrderNo(mallOrderBase.getOrderCode());
            invoiceDetailDto.setOrderName(mallOrderBase.getGoodContant());
            invoiceDetailDto.setMemberNo(mallOrderBase.getMemberNo());
            invoiceDetailDto.setPbChannel(ApiThreadLocal.getPbChannel());
            invoiceDetailDto.setOrderType(OrderTypeConstant.MALL);
            invoiceDetailDto.setPbChannel(ApiThreadLocal.getPbChannel());
            InvoiceBaseParamDto invoiceBaseParamDto = new InvoiceBaseParamDto();
            invoiceBaseParamDto.setInvoiceDetailDto(invoiceDetailDto);
            mnsUtil.putMessageToQueue(RodimusMnsConstant.QUEUE_ORDER_INVOICE, JacksonUtil.beanToJson(invoiceBaseParamDto));
        }
        MallOrderCancelParamDto cancelParam = new MallOrderCancelParamDto();
        cancelParam.setOrderNo(mallOrderBase.getOrderCode());
        mnsUtil.putDelayMessageToQueue(RodimusMnsConstant.QUEUE_MALL_ORDER_CANCEL, JacksonUtil.beanToJson(cancelParam), autoCancelSecond + 300);
        // 3.保存订单信息及物品信息
        MallOrderBaseDto mallOrderBaseResult = new MallOrderBaseDto();
        ClassConverUtil.copyProperties(mallOrderBase, mallOrderBaseResult);
       /* if( null!=preorderSignResDto && PayConstant.CHANNEL.WX.equals(preorderSignResDto.getChannel() ) ){
            mallOrderBaseResult.setWxSignMap(JacksonUtil.jsonToBean(JacksonUtil.beanToJson(preorderSignResDto.getWxBrandWCPayResDto()), HashMap.class) );
        }*/
        publisher.publishEvent(new MallOrderPaySuccessEvent(mallOrderBase.getLhotelGroupCode(), mallOrderBase.getOrderCode()));
        return mallOrderBaseResult;
    }

    private void checkInvoice(InvoiceDetailDto invoiceDetailDto) {
        InvoiceUtil.checkInvoice(invoiceDetailDto);
    }


    private SalesmanBase findSalemanByMobile(String lhotelGroupCode, String mobile) {
        SalesmanBase find = new SalesmanBase();
        find.setLhotelGroupCode(lhotelGroupCode);
        find.setMobile(mobile);
        try {
            return commonService.findOneEQ(SalesmanBase.class, find);
        } catch (Exception e) {
            ExceptionUtil.getExceptionDetail(e);
            return null;
        }
    }

    @Override
    public QueryResult<MallAddress> getAddressList(MallAddressApiParamDto mallAddressApiParamDto) throws Exception {
        MemberSessionDto memberSession = ApiThreadLocal.getMemberSessionThreadLocal();
        MallAddress mallAddress = new MallAddress();
        mallAddress.setLhotelGroupCode(mallAddressApiParamDto.getLhotelGroupCode());
        mallAddress.setMemberNo(memberSession.getMemberNo());
        QueryResult<MallAddress> mallAddressQueryResult = null;
        if (StringUtil.isNotBlank(memberSession.getMemberNo())) {
            mallAddressQueryResult = commonService.findAllEQ(MallAddress.class, mallAddress, mallAddressApiParamDto.getCurrentPage(), mallAddressApiParamDto.getPageSize());
        }
        return mallAddressQueryResult;
    }

    @Override
    public MallAddress getAddress(MallAddressApiParamDto mallAddressApiParamDto) throws Exception {
        MemberSessionDto memberSession = ApiThreadLocal.getMemberSessionThreadLocal();
        MallAddress mallAddress = new MallAddress();
        mallAddress.setLhotelGroupCode(mallAddressApiParamDto.getLhotelGroupCode());
        mallAddress.setMemberNo(memberSession.getMemberNo());
        mallAddress.setId(mallAddressApiParamDto.getId());
        mallAddress = commonService.findOneEQ(MallAddress.class, mallAddress);
        return mallAddress;
    }

    @Override
    public void newAddress(MallAddressApiParamDto mallAddressApiParamDto) throws Exception {

        MemberSessionDto memberSession = ApiThreadLocal.getMemberSessionThreadLocal();
        MallAddress mallAddress = new MallAddress();
        mallAddress.setLhotelGroupCode(mallAddressApiParamDto.getLhotelGroupCode());
        mallAddress.setMemberNo(memberSession.getMemberNo());
        mallAddress.setIsDefault(MallAdderssConstant.defaultAddress.isDefault);
        Long count = commonService.getCountAllEQ(MallAddress.class, mallAddress, null);

        //mallAddress.setId( mallAddressApiParamDto.getId());
        mallAddress.setName(mallAddressApiParamDto.getName());
        mallAddress.setAddress(mallAddressApiParamDto.getAddress());
        mallAddress.setMobile(mallAddressApiParamDto.getMobile());
        mallAddress.setArea(mallAddressApiParamDto.getArea());
        if (count.compareTo(Long.parseLong("0")) != 0) {
            mallAddress.setIsDefault(MallAdderssConstant.defaultAddress.notDefault);
        } else {
            mallAddress.setIsDefault(MallAdderssConstant.defaultAddress.isDefault);
        }

        commonService.save(mallAddress);
        //return  mallAddress;
    }

    @Override
    public void deleteAddress(MallAddressApiParamDto mallAddressApiParamDto) throws Exception {
        commonService.delete(MallAddress.class, mallAddressApiParamDto.getId());
    }

    @Override
    public void modifyAddress(MallAddressApiParamDto mallAddressApiParamDto) throws Exception {
        MemberSessionDto memberSession = ApiThreadLocal.getMemberSessionThreadLocal();
        MallAddress mallAddress = new MallAddress();
        mallAddress.setMemberNo(memberSession.getMemberNo());
        mallAddress.setIsDefault(MallAdderssConstant.defaultAddress.isDefault);
        QueryResult<MallAddress> mallAddressQueryResult = commonService.findAllEQ(MallAddress.class, mallAddress);
        if (null != mallAddressQueryResult && mallAddressQueryResult.getResultlist().size() > 0) {
            for (MallAddress ma : mallAddressQueryResult.getResultlist()) {
                ma.setIsDefault(MallAdderssConstant.defaultAddress.notDefault);
                commonService.merge(ma);
            }
        }
        mallAddress = new MallAddress();
        mallAddress.setLhotelGroupCode(mallAddressApiParamDto.getLhotelGroupCode());
        mallAddress.setMemberNo(memberSession.getMemberNo());
        mallAddress.setId(mallAddressApiParamDto.getId());
        mallAddress = commonService.findOneEQ(MallAddress.class, mallAddress);

        mallAddress.setName(mallAddressApiParamDto.getName());
        mallAddress.setAddress(mallAddressApiParamDto.getAddress());
        mallAddress.setMobile(mallAddressApiParamDto.getMobile());
        mallAddress.setArea(mallAddressApiParamDto.getArea());
        mallAddress.setIsDefault(mallAddressApiParamDto.getIsDefault());
        commonService.merge(mallAddress);
    }

    @Override
    public MallOrderBaseDto prepay(MallOrderPrepayParamDto prepayParamDto) throws Exception {
        String mallOrderNo = prepayParamDto.getMallOrderNo();
        L2RAssert.stringBlank(mallOrderNo, "[mallOrderNo] is null.");
        MemberSessionDto memberSession = ApiThreadLocal.getMemberSessionThreadLocal();
        MallOrderBase find = new MallOrderBase();
        find.setOrderCode(mallOrderNo);
        MallOrderBase mallOrderBase = commonService.findOneEQ(MallOrderBase.class, find);

        if (MallOrderConstant.Sta.needPay.equals(mallOrderBase.getSta())) {

            MallOrderPrice mallOrderPrice = new MallOrderPrice();
            mallOrderPrice.setLhotelGroupCode(prepayParamDto.getLhotelGroupCode());
            mallOrderPrice.setOrderCode(mallOrderBase.getOrderCode());
            QueryResult<MallOrderPrice> mallOrderPriceQueryResult = commonService.findAllEQ(MallOrderPrice.class, mallOrderPrice);

            PrePayParamDto payParamDto = new PrePayParamDto();
            payParamDto.setPayChannel(prepayParamDto.getPayChannel());
            payParamDto.setPayType(prepayParamDto.getPayType());
            payParamDto.setLhotelGroupCode(prepayParamDto.getLhotelGroupCode());
            payParamDto.setLhotelCode(prepayParamDto.getLhotelCode());
            payParamDto.setSpBillCreateIP(BaseThreadLocal.getRemoteAddr());
            payParamDto.setGoodName("商城物品");
            payParamDto.setOpenid(memberSession.getOpenid());
            if (CollectionUtils.isNotEmpty(mallOrderPriceQueryResult.getResultlist())) {
                payParamDto.setGoodsTag(mallOrderPriceQueryResult.getResultlist().get(0).getPriceCode());
            }
            payParamDto.setOrderNo(mallOrderBase.getOrderCode());
            payParamDto.setTotalFee(mallOrderBase.getPrice());
            payParamDto.setNotifyService(BaseConstant.ServiceCategoryConstant.RODIMUS);
            payParamDto.setOrderType(Pay._OrderType.MALL);
            PrepayResDto payRes = prepayFeignService.unifiedorderSign(payParamDto).getResultInfo();
            String l2rPrepayId = payRes.getL2rPrepayId();
            MallOrderBaseDto mallOrderBaseDto = new MallOrderBaseDto();
            mallOrderBaseDto.setL2rPrepayId(l2rPrepayId);
            return mallOrderBaseDto;
        } else {
            return null;
        }
    }

    /**
     * 商城订单自动取消
     * 若到取消时间 ->需要付款订单 且 未支付  ->订单取消,扣除的积分归还
     *
     * @param paramDto
     * @throws Exception
     */
    @Override
    public void autoCancelOrder(MallOrderCancelParamDto paramDto) throws Exception {
        String lhotelGroupCode = paramDto.getLhotelGroupCode();
        L2RAssert.stringBlank(lhotelGroupCode, "[lhotelGroupCode] is null.");
        String orderNo = paramDto.getOrderNo();
        L2RAssert.stringBlank(orderNo, "[orderNo] is null.");

        MallOrderBase find = new MallOrderBase();
        find.setOrderCode(orderNo);
        MallOrderBase qres = commonService.findOneEQ(MallOrderBase.class, find);
        L2RAssert.isTrue(qres == null, new SysException(MALL_ORDER_CANCEL_ERROR, "订单不存在."));
        L2RAssert.isTrue(MallOrderConstant.MoneyPaySat.PAID.equals(qres.getMoneyPaySta()), new SysException(MALL_ORDER_CANCEL_ERROR, "订单已经付款不能取消."));
        if (MallOrderConstant.Sta.cancel.equals(qres.getSta())) {
            return;
        }
        //需要付款的才进来进行取消操作
        if (MallOrderConstant.Sta.needPay.equals(qres.getSta())) {
            if (MallOrderConstant.MoneyPaySat.PAID.equals(qres.getMoneyPaySta())) {//订单已经付款不能取消
                return;
            } else {
                if (MallOrderConstant.ORDER_TYPE.GROUP_BUYING.equals(qres.getOrderType())) {//团购订单处理
                    groupBuyingService.teamAutoCancel(qres);
                } else {
                    //积分支付成功，则加回去
                    if (MallOrderConstant.PointPaySat.PAID.equals(qres.getPointPaySta()) &&
                            (qres.getPoint() != null || BigDecimal.ZERO.compareTo(qres.getPoint()) > 0)) {
                        addPMSPoint(qres.getMemberNo(), qres.getPoint(), "商城订单取消",qres.getGoodType());
                    }
                    qres.setSta(MallOrderConstant.Sta.cancel);
                    commonService.merge(qres);
                }
            }
        }
    }

    private void addPMSPoint(String l2rMemberNo, BigDecimal point, String remark,String goodType) throws Exception {
        if (StringUtil.isBlank(l2rMemberNo)) {
            return;
        }
        PointPresentUseInsideParamDto pointPresentUseInsideParamDto = new PointPresentUseInsideParamDto();
        pointPresentUseInsideParamDto.setL2rMemberNo(l2rMemberNo);
        pointPresentUseInsideParamDto.setRemark(remark);
        pointPresentUseInsideParamDto.setPoint(point);
        pointPresentUseInsideParamDto.setSrcType(L2RPointConstant.SRC_TYPE.MALL);
        if(MallGoodsConstant.GoodType.PMSPACKAGE.equals(goodType)){
            pointPresentUseInsideParamDto.setGoodType(L2RPointConstant.GOOD_TYPE.PMSPACKAGE);
        }
        pmsMemberFeignService.addPoint(pointPresentUseInsideParamDto);
    }
}
